package com.http;

import com.FileBehavior.FileHelp;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.util.ArrayList;

public class HttpRequest {

    public static JSONObject GetRequestHead(String url, JSONObject head) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        for(String key:head.keySet()){
            httpGet.setHeader(key, head.get(key).toString());
        }
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if(entity!=null){
            String result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
            httpGet.releaseConnection();
            return JSONObject.parseObject(result);
        }
        //RestTemplate client = new RestTemplate();
        //String body = client.getForEntity(url, String.class).getBody();
        return new JSONObject();
    }

    public static JSONObject PostRequest(String url) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        JSONObject o = tryToRequest(client, httpPost);
        if (o != null) return o;
        return null;
    }

    @Nullable
    private static JSONObject tryToRequest(HttpClient client, HttpPost httpPost) throws IOException {
        HttpResponse response = client.execute(httpPost);
        HttpEntity entity = response.getEntity();

        if (null != entity) {
            String result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
            httpPost.releaseConnection();
            JSONObject o = JSONObject.parseObject(result);
            if(o.get("errno") == null || o.get("errno").equals(0)){
                return o;
            }
            else if(o.get("errno").equals(2) && 0==((JSONArray)o.get("info")).size()){
                // 怪异的这种情况，参数正确，多次之后就正常了
                System.out.println("怪异的失败，准备重试...");
                int retryCount = 10;
                for(int i=0; i < retryCount; ++i){
                    System.out.println("重试次数:" + (i + 1) + "/" + retryCount);
                    response = client.execute(httpPost);
                    entity = response.getEntity();
                    if(null != entity){
                        result = EntityUtils.toString(entity, "UTF-8");
                        EntityUtils.consume(entity);
                        httpPost.releaseConnection();
                        o = JSONObject.parseObject(result);
                        if(o.get("errno") == null || o.get("errno").equals(0)){
                            System.out.println("重试成功...");
                            return o;
                        }
                    }
                }
                System.out.println("重试失败...");
                return o;
            }else{
                return o;
            }
        }


        httpPost.releaseConnection();
        return null;
    }

    public static String joinJSONObjectByUrl(JSONObject body){
        ArrayList<String> arrayList = new ArrayList<>();
        for(String key: body.keySet()){
            String s = key + "=" + body.get(key).toString();
            arrayList.add(s);
        }
        return String.join("&", arrayList);
    }

    public static JSONObject PostRequestFormUrlencoded(String url, JSONObject body){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        RestTemplate restTemplate = new RestTemplate();

        String bodyString = joinJSONObjectByUrl(body);
        org.springframework.http.HttpEntity<String> r = new org.springframework.http.HttpEntity<>(bodyString, headers);

        ResponseEntity<String> result = restTemplate.postForEntity(url, r, String.class);

        JSONObject resultJson = JSON.parseObject(result.getBody());

        return resultJson;
    }

    public static JSONObject PostRequest(String url, JSONObject body) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        // 设置body
        String bodyString = joinJSONObjectByUrl(body);
        StringEntity stringEntity = new StringEntity(bodyString, ContentType.APPLICATION_JSON);
        stringEntity.setContentEncoding("UTF-8");
        httpPost.setEntity(stringEntity);
        JSONObject o = tryToRequest(client, httpPost);
        if (o != null) return o;
        return new JSONObject();
    }

    public static JSONObject GetRequest(String url) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();

        if (null != entity) {
            String result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
            httpGet.releaseConnection();
            return JSONObject.parseObject(result);
        }
        httpGet.releaseConnection();
        return new JSONObject();
    }
    
    public static JSONObject downloadFile(String url, JSONObject header, String fileName, boolean deleteOnExit) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        for(String key:header.keySet()){
            httpGet.setHeader(key, header.get(key).toString());
        }
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        File file = FileHelp.createFile(fileName);
        JSONObject result = new JSONObject();
        if(file==null){
            result.put("res", "file_error");
            return result;
        }
        System.out.println(entity);
        if(null !=entity){
            FileOutputStream fos = new FileOutputStream(file);
            entity.writeTo(fos);
            System.out.println("下载了");
            fos.flush();
            fos.close();
        }
        if(deleteOnExit){
            file.deleteOnExit();
        }
        result.put("res", "suc");
        result.put("path", FileHelp.absoPathToRelaPath(file.getAbsolutePath()));
        return result;
    }

    public static JSONObject uploadFile(String url, File file){
        // https://blog.csdn.net/Baldprogrammer/article/details/116892593
        try{
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setContentType(ContentType.MULTIPART_FORM_DATA);
            builder.addBinaryBody("file", file);
            CloseableHttpClient client = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            CloseableHttpResponse response = client.execute(httpPost);
            entity = response.getEntity();
            if (null != entity) {
                String result = EntityUtils.toString(entity, "UTF-8");
                EntityUtils.consume(entity);
                response.close();
                return JSONObject.parseObject(result);
            }
            response.close();
            return new JSONObject();
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
